package jacky.utils;

import android.content.Context;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.util.Log;

import com.jacky.jpeg.RenderScriptRotation;
import com.jacky.log.Logger;

import java.io.ByteArrayOutputStream;
import java.io.Closeable;
import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.nio.ByteBuffer;

/**
 * https://github.com/AndroidDeveloperLB/AndroidJniBitmapOperations
 */
public class BitmapConvert {

    static {
        System.loadLibrary("bitmap_convert");
    }

    private native ByteBuffer jniStoreBitmapData(Bitmap bitmap);

    private native Bitmap jniGetBitmapFromStoredBitmapData(ByteBuffer handler);
    private native void jniFreeBitmapData(ByteBuffer handler);
    /**
     * 逆时针旋转90度
     */
    private native void jniRotateBitmapCcw90(ByteBuffer handler);
    /**
     * 顺时针旋转90度
     */
    private native void jniRotateBitmapCw90(ByteBuffer handler);

    private native void jniRotateBitmap180(ByteBuffer handler);

    private ByteBuffer _handler = null;

    public BitmapConvert(final Bitmap bitmap) {
        storeBitmap(bitmap);
    }

    public BitmapConvert() {}

    public void storeBitmap(final Bitmap bitmap) {
        if (_handler != null)
            freeBitmap();
        _handler = jniStoreBitmapData(bitmap);
    }

    public void rotateBitmap270() {
        if (_handler == null)
            return;
        jniRotateBitmapCcw90(_handler);
    }

    public void rotateBitmap90() {
        if (_handler == null)
            return;
        jniRotateBitmapCw90(_handler);
    }

    public void rotateBitmap180() {
        if (_handler == null)
            return;
        jniRotateBitmap180(_handler);
    }

//    public void rotateBitmap180()
//    {
//        if(_handler==null)
//            return;
//        jniRotateBitmap180(_handler);
//    }

//    public void cropBitmap(final int left,final int top,final int right,final int bottom)
//    {
//        if(_handler==null)
//            return;
//        jniCropBitmap(_handler,left,top,right,bottom);
//    }

    private Bitmap getBitmap() {
        if (_handler == null)
            return null;
        return jniGetBitmapFromStoredBitmapData(_handler);
    }

    public Bitmap getBitmapAndFree() {
        final Bitmap bitmap = getBitmap();
        freeBitmap();
        return bitmap;
    }

//    public void scaleBitmap(final int newWidth,final int newHeight,final ScaleMethod scaleMethod)
//    {
//        if(_handler==null)
//            return;
//        switch(scaleMethod)
//        {
//            case BilinearInterpolation:
//                jniScaleBIBitmap(_handler,newWidth,newHeight);
//                break;
//            case NearestNeighbour:
//                jniScaleNNBitmap(_handler,newWidth,newHeight);
//                break;
//        }
//    }

//    /**
//     * 水平翻转图片<br/>
//     *
//     * <pre>
//     * 123    321
//     * 456 => 654
//     * 789    987
//     * </pre>
//     */
//    //
//    public void flipBitmapHorizontal()
//    {
//        if(_handler==null)
//            return;
//        jniFlipBitmapHorizontal(_handler);
//    }

//    /**
//     * 垂直翻转位图<br/>
//     *
//     * <pre>
//     * 123    789
//     * 456 => 456
//     * 789    123
//     * </pre>
//     */
//    public void flipBitmapVertical()
//    {
//        if(_handler==null)
//            return;
//        jniFlipBitmapVertical(_handler);
//    }

    public void freeBitmap() {
        if (_handler == null)
            return;
        jniFreeBitmapData(_handler);
        _handler = null;
    }

    @Override
    protected void finalize() throws Throwable {
        super.finalize();
        if (_handler == null)
            return;
        Log.w("DEBUG", "JNI bitmap wasn't freed nicely.please remember to free the bitmap as soon as you can");
        freeBitmap();
    }

    public static void saveImage(Context context, int rotate, byte[] bitmapDatas, File file, boolean removeIccProf) {
        if(rotate == 0) {
            //不需要旋转的图片，直接写入磁盘
            writeData(bitmapDatas, file);
            return;
        }

        Bitmap bm  = BitmapFactory.decodeByteArray(bitmapDatas, 0, bitmapDatas.length);
        bitmapDatas = null;

        BitmapConvert convert = new BitmapConvert(bm);
        if(rotate == 90) {
            convert.rotateBitmap90();
        } else if(rotate == 180) {
            convert.rotateBitmap180();
        } else if(rotate == 270){
            convert.rotateBitmap270();
        } else {
            throw new IllegalArgumentException("rotate err,only 90/180/270.but input " + rotate);
        }
        bm = convert.getBitmapAndFree();

        if(removeIccProf) {
            ByteArrayOutputStream baos = new ByteArrayOutputStream();
            bm.compress(Bitmap.CompressFormat.JPEG,90,baos);
            bm.recycle();
            bitmapDatas = baos.toByteArray();
            bitmapDatas = skipBitmapIccProf(bitmapDatas);
            writeData(bitmapDatas, file);
        } else {
            FileOutputStream stream2 = null;
            try {
                stream2 = new FileOutputStream(file);
                bm.compress(Bitmap.CompressFormat.JPEG, 90, stream2);
                bm.recycle();
            } catch (Exception e) {
                Logger.e(e);
            } finally {
                close(stream2);
            }
        }
    }

    private static void close(Closeable closeable) {
        if(closeable == null) return;
        try {
            closeable.close();
        } catch (IOException e) {
        }
    }

    private static void writeData(byte[] datas, File file) {
        FileOutputStream stream2 = null;
        try {
            stream2 = new FileOutputStream(file);
            stream2.write(datas);
        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            close(stream2);
        }
    }

    private static byte[] skipBitmapIccProf(byte[] datas) {
        int startPos = -1, iccLength = 0;
        for(int i = 2; i < 300;i++) {//2和200没什么意义，只是减少次数而已
            //0x02  0x40  0x49  0x43  0x43
            if(datas[i] !=  0x02) continue;
            if(datas[i + 1] !=  0x40) continue;
            if(datas[i + 2] !=  0x49) continue;
            if(datas[i + 3] !=  0x43) continue;
            if(datas[i + 4] !=  0x43) continue;

            //找到了ICC标识的位置
            startPos = i - 2;
            iccLength = datas[i - 1] & 0xff;//ICC_PROF属性的数据范围长度
            break;
        }

        if(startPos == -1)  return datas;
        byte[] dd = new byte[datas.length - iccLength];
        System.arraycopy(datas, 0, dd, 0, startPos);
        System.arraycopy(datas, startPos + iccLength, dd, startPos, dd.length - startPos);
        return dd;
    }
}
